Release 10.1A: OpenEdge Development:
Progress 4GL Handbook
Using widget pools
Deleting individual dynamic objects is a big responsibility, and a serious nuisance as well. Widget pools are designed to help you make your use of dynamic objects much simpler and more reliable.
A widget pool provides a means of treating objects you create as a set. When you delete the pool, all the objects you created in it go away together. The simplest way to group objects using widget pools is to associate all the objects in a single procedure with a widget pool. In fact, the template procedures used by the AppBuilder for windows (and for visual SmartObjects, such as SmartWindows and SmartDataViewers) help you do this by having a
CREATE WIDGET-POOLstatement in the template’s definitions section:
This means that, by default, all the dynamic objects you create that go into the window are deleted when the window is closed and its procedure deleted. This includes not just visual objects but dynamic buffers, queries, and so forth.
Remember that a simple
CREATE WIDGET-POOLstatement creates an unnamed widget pool. This pool automatically goes away when its procedure terminates. This might not always be the behavior you want. In fact, by passing the handles to dynamic objects around, you can easily wind up with a handle whose scope exceeds the lifetime of the dynamic object it points to. In this case, the value of the handle can become invalid.Here’s a simple example of how this can happen. The
h-MakeBuffer.pprocedure has an internal procedure calledgetBufferthat creates a dynamic buffer and returns it to the caller. TheCREATE WIDGET-POOLstatement puts all such buffers into an unnamed widget pool for that procedure:
Another procedure,
h-RunMakeBuff.p, runsh-MakeBuffer.pPERSISTENTand then runsgetBuffer:
The first message statement, as expected, correctly displays the name of the dynamic buffer that was returned, as shown in Figure 21–6.
Figure 21–6: Result of widget pool example
![]()
What happens, though, when the procedure has deleted its instance of
h-MakeBuffer.p?The unnamed widget pool in that instance of
h-MakeBuffer.pgoes away, and the dynamic buffer thathMyBufpoints to goes away with it. But thehMyBufvariable is still very much alive, and in fact the value of the handle that it holds hasn’t changed. However, that handle value doesn’t point to anything anymore, so you get a string of errors, as shown in Figure 21–7.Figure 21–7: Errors for unnamed widget pool example
![]()
This sequence of errors is the bane of any dynamic programmer’s existence. It is the most likely consequence of failing to make sure that all your dynamic objects live exactly as long as they need to, but no longer.
Using named widget pools
The solution to this is to give names to widget pools that hold objects that might outlive the procedure that created them. In addition to giving the pool a name, you must also define it to be
PERSISTENT. You can then create dynamic objects explicitly in that pool:
The persistent widget pool becomes another dynamic object that your application has to take responsibility for managing. You must delete it when you’re finally done with, or all the objects in it will sit there in memory until your session ends. Here the calling procedure cleans up after it is done using the buffer handle:
When you run the procedure, the errors go away as shown in Figure 21–8, because the handle is valid until you delete the pool.
Figure 21–8: Result of named widget pool example
![]()
Remember that all these steps are important:
- You must give the widget pool a name if you want to allocate objects to it specifically or if you want it to outlive the procedure that creates it.
- The widget pool name is a character expression. So, if you are using a literal string rather than a variable for the name, you must remember to put it in quotes both where you create it and wherever you reference it. This is different from other
CREATEstatements, where you normally specify a handle variable as a target for the create and where the dynamic object you create doesn’t really have a name the same way that static objects do.- You must also make a named pool
PERSISTENTif you want it to outlive the procedure that creates it.- You must remember to delete the widget pool when you are done using it, just as you delete individual dynamic objects that aren’t in a specific widget pool when you are done with them.
You might create a named widget pool that was not persistent simply to put different dynamic objects in different pools within a single procedure, so that you could delete one widget pool within the procedure without deleting objects in some other widget pool. In this case, all of the pools that haven’t been specifically deleted during the execution of the procedure are deleted when the procedure is deleted.
A widget pool cannot be created as
PERSISTENTwithout giving it a name.When you create a persistent named pool, its name effectively becomes global to the session. Any procedure running anywhere in the session can delete it. You cannot, however, access named widget pools through the
SESSIONhandle as you can with some other kinds of objects, such as windows and procedures.
|
Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |